"use strict";

var $ = require("jquery"),
    Color = require("../../color"),
    ColorView = require("./color_view"),
    registerComponent = require("../../core/component_registrator"),
    DropDownEditor = require("../drop_down_editor/ui.drop_down_editor");

var COLOR_BOX_CLASS = "dx-colorbox",
    COLOR_BOX_INPUT_CLASS = COLOR_BOX_CLASS + "-input",
    COLOR_BOX_INPUT_CONTAINER_CLASS = COLOR_BOX_INPUT_CLASS + "-container",
    COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS = COLOR_BOX_CLASS + "-color-result-preview",
    COLOR_BOX_COLOR_IS_NOT_DEFINED = COLOR_BOX_CLASS + "-color-is-not-defined",
    COLOR_BOX_OVERLAY_CLASS = COLOR_BOX_CLASS + "-overlay",

    COLOR_BOX_CONTAINER_CELL_CLASS = "dx-colorview-container-cell",
    COLOR_BOX_BUTTON_CELL_CLASS = "dx-colorview-button-cell",
    COLOR_BOX_BUTTONS_CONTAINER_CLASS = "dx-colorview-buttons-container",
    COLOR_BOX_APPLY_BUTTON_CLASS = "dx-colorview-apply-button",
    COLOR_BOX_CANCEL_BUTTON_CLASS = "dx-colorview-cancel-button";

var colorEditorPrototype = ColorView.prototype,
    colorUtils = {
        makeTransparentBackground: $.proxy(colorEditorPrototype._makeTransparentBackground, colorEditorPrototype),
        makeRgba: $.proxy(colorEditorPrototype._makeRgba, colorEditorPrototype)
    };

var ColorBox = DropDownEditor.inherit({

    _supportedKeys: function() {
        var arrowHandler = function(e) {
            e.stopPropagation();
            if(this.option("opened")) {
                e.preventDefault();
                return true;
            }
        };

        var upArrowHandler = function(e) {
            if(!this.option("opened")) {
                e.preventDefault();
                return false;
            }
            if(e.altKey) {
                this.close();
                return false;
            }
            return true;
        };

        var downArrowHandler = function(e) {
            if(!this.option("opened") && !e.altKey) {
                e.preventDefault();
                return false;
            }
            if(!this.option("opened") && e.altKey) {
                this._validatedOpening();
                return false;
            }
            return true;
        };

        return $.extend(this.callBase(), {
            tab: function(e) {
                if(this.option("opened")) {
                    e.preventDefault();
                    this._colorView._rgbInputs[0].focus();
                }
            },
            enter: this._enterKeyHandler,
            leftArrow: arrowHandler,
            rightArrow: arrowHandler,
            upArrow: upArrowHandler,
            downArrow: downArrowHandler
        });
    },

    _getDefaultOptions: function() {
        return $.extend(this.callBase(), {
            /**
            * @name dxColorBoxOptions_editAlphaChannel
            * @publicName editAlphaChannel
            * @type boolean
            * @default false
            */
            editAlphaChannel: false,

            /**
            * @name dxColorBoxOptions_applyButtonText
            * @publicName applyButtonText
            * @type string
            * @default "OK"
            */

            /**
            * @name dxColorBoxOptions_cancelButtonText
            * @publicName cancelButtonText
            * @type string
            * @default "Cancel"
            */

            /**
            * @name dxColorBoxOptions_applyValueMode
            * @publicName applyValueMode
            * @type string
            * @default "useButtons"
            * @extend_doc
            */
            applyValueMode: "useButtons",

            /**
            * @name dxColorBoxOptions_keyStep
            * @publicName keyStep
            * @type number
            * @default 1
            */
            keyStep: 1,

            /**
             * @name dxColorBoxOptions_fieldTemplate
             * @publicName fieldTemplate
             * @type template
             * @default null
             * @type_function_param1 value:string
             * @type_function_param2 fieldElement:jQuery
             * @type_function_return string|Node|jQuery
             */
            fieldTemplate: null,

            // TODO: convert these options to actions and publish them
            onApplyButtonClick: null,
            onCancelButtonClick: null,

            buttonsLocation: "bottom after"

            /**
            * @name dxColorBoxOptions_value
            * @publicName value
            * @type string
            * @extend_doc
            */

            /**
            * @name dxColorBoxOptions_fieldEditEnabled
            * @publicName fieldEditEnabled
            * @hidden
            * @extend_doc
            */

            /**
            * @name dxColorBoxOptions_maxLength
            * @publicName maxLength
            * @hidden
            * @extend_doc
            */

            /**
            * @name dxColorBoxOptions_showClearButton
            * @publicName showClearButton
            * @hidden
            * @extend_doc
            */

            /**
            * @name dxColorBoxOptions_valueChangeEvent
            * @publicName valueChangeEvent
            * @hidden
            * @extend_doc
            */

            /**
            * @name dxColorBoxOptions_spellcheck
            * @publicName spellcheck
            * @hidden
            * @extend_doc
            */
        });
    },

    _popupConfig: function() {
        return $.extend(this.callBase(), {
            height: "auto",
            width: ""
        });
    },

    _contentReadyHandler: function() {
        this._createColorView();
        this._addPopupBottomClasses();
    },

    _addPopupBottomClasses: function() {
        var $popupBottom = this._popup.bottomToolbar();
        if($popupBottom) {
            $popupBottom
                .addClass(COLOR_BOX_CONTAINER_CELL_CLASS)
                .addClass(COLOR_BOX_BUTTON_CELL_CLASS)
                .find(".dx-toolbar-items-container")
                .addClass(COLOR_BOX_BUTTONS_CONTAINER_CLASS);

            $popupBottom
                .find(".dx-popup-done")
                .addClass(COLOR_BOX_APPLY_BUTTON_CLASS);

            $popupBottom
                .find(".dx-popup-cancel")
                .addClass(COLOR_BOX_CANCEL_BUTTON_CLASS);
        }
    },

    _createColorView: function() {
        this._popup.overlayContent().addClass(COLOR_BOX_OVERLAY_CLASS);

        var $colorView = $("<div>").appendTo(this._popup.content());

        this._colorView = this._createComponent($colorView, ColorView, this._colorViewConfig());

        $colorView.on("focus", $.proxy(function() {
            this.focus();
        }, this));
    },

    _applyNewColor: function(value) {
        this.option("value", value);

        if(value) {
            colorUtils.makeTransparentBackground(this._$colorResultPreview, value);
        }

        if(this._colorViewEnterKeyPressed) {
            this.close();
            this._colorViewEnterKeyPressed = false;
        }
    },

    _colorViewConfig: function() {
        var that = this;

        return {
            value: that.option("value"),
            editAlphaChannel: that.option("editAlphaChannel"),
            applyValueMode: that.option("applyValueMode"),
            focusStateEnabled: that.option("focusStateEnabled"),
            onEnterKeyPressed: function() {
                that._colorViewEnterKeyPressed = true;
                if(that._colorView.option("value") !== that.option("value")) {
                    that._applyNewColor(that._colorView.option("value"));
                    that.close();
                }
            },

            onValueChanged: function(args) {
                var instantlyMode = that.option("applyValueMode") === "instantly";

                if(!instantlyMode && !that._colorViewEnterKeyPressed) {
                    return;
                }

                that._applyNewColor(args.value);
            },
            _keyboardProcessor: that._colorViewProcessor
        };
    },

    _enterKeyHandler: function() {
        var newValue = this._input().val(),
            value = this.option("value"),
            oldValue = this.option("editAlphaChannel") ? colorUtils.makeRgba(value) : value;

        if(!newValue) return false;

        var color = new Color(newValue);

        if(color.colorIsInvalid) {
            this._input().val(oldValue);
            return;
        }

        if(newValue !== oldValue) {
            this._applyColorFromInput(newValue);
            this.option("value", this.option("editAlphaChannel") ? colorUtils.makeRgba(newValue) : newValue);
        }

        if(this._colorView) {
            var colorViewValue = this._colorView.option("value");
            if(value !== colorViewValue) {
                this.option("value", colorViewValue);
            }
        }

        this.close();
        return false;
    },

    _applyButtonHandler: function() {
        this._applyNewColor(this._colorView.option("value"));

        if($.isFunction(this.option("onApplyButtonClick"))) {
            this.option("onApplyButtonClick")();
        }

        this.callBase();
    },

    _cancelButtonHandler: function() {
        this._resetInputValue();

        if($.isFunction(this.option("onCancelButtonClick"))) {
            this.option("onCancelButtonClick")();
        }

        this.callBase();
    },

    _attachChildKeyboardEvents: function() {
        this._colorViewProcessor = this._keyboardProcessor.attachChildProcessor();
        if(this._colorView) {
            this._colorView.option("_keyboardProcessor", this._colorViewProcessor);
            return;
        }
    },

    _init: function() {
        this.callBase();
    },

    _render: function() {
        this.callBase();
        this.element().addClass(COLOR_BOX_CLASS);
    },

    _renderInput: function() {
        this.callBase();

        this._input().addClass(COLOR_BOX_INPUT_CLASS);
        this._renderColorPreview();
    },

    _renderColorPreview: function() {
        this.element().wrapInner($("<div/>").addClass(COLOR_BOX_INPUT_CONTAINER_CLASS));
        this._$colorBoxInputContainer = this.element().children().eq(0);

        this._$colorResultPreview = $("<div>", {
            "class": COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS,
            "appendTo": this._$colorBoxInputContainer
        });

        if(!this.option("value")) {
            this._$colorBoxInputContainer.addClass(COLOR_BOX_COLOR_IS_NOT_DEFINED);
        } else {
            colorUtils.makeTransparentBackground(this._$colorResultPreview, this.option("value"));
        }
    },

    _renderValue: function() {
        var value = this.option("value");
        this.option("text", this.option("editAlphaChannel") ? colorUtils.makeRgba(value) : value);
        this.callBase();
    },

    _resetInputValue: function() {
        var $input = this._input(),
            value = this.option("value");

        $input.val(value);
        this._colorView && this._colorView.option("value", value);
    },

    _valueChangeEventHandler: function(e) {
        var value = this._input().val();

        if(value) {
            value = this._applyColorFromInput(value);

            this._colorView && this._colorView.option("value", value);
        }
        this.callBase(e, value);
    },

    _applyColorFromInput: function(value) {
        var newColor = new Color(value);

        if(newColor.colorIsInvalid) {
            this._resetInputValue();
            value = this.option("value");
        }

        return value;
    },

    _optionChanged: function(args) {
        var value = args.value,
            name = args.name;

        switch(name) {
            case "value":
                this._$colorBoxInputContainer.toggleClass(COLOR_BOX_COLOR_IS_NOT_DEFINED, !value);

                if(value) {
                    colorUtils.makeTransparentBackground(this._$colorResultPreview, value);
                } else {
                    this._$colorResultPreview.removeAttr("style");
                }

                if(this._colorView) {
                    this._colorView.option("value", value);
                }

                this.callBase(args);
                break;
            case "applyButtonText":
            case "cancelButtonText":
                this.callBase(args);
                this._popup && this._addPopupBottomClasses();
                break;
            case "editAlphaChannel":
            case "onCancelButtonClick":
            case "onApplyButtonClick":
            case "keyStep":
                if(this._colorView) {
                    this._colorView.option(name, value);
                }
                break;
            case "applyValueMode":
                this.callBase(args);
                break;
            case "rtlEnabled":
                if(this._colorView) {
                    this._colorView.option(name, value);
                }
                this.callBase(args);
                break;
            default:
                this.callBase(args);
        }
    }
});

registerComponent("dxColorBox", ColorBox);

module.exports = ColorBox;
